﻿using System;
using System.Collections.Generic;
using System.Text;
using jade.domain.FIPAAgentManagement;
using jade.domain;
using jade.core;
using System.Diagnostics;
using System.Windows.Forms;
using TravelLib;

namespace MultiAgentLib
{
    /// <summary> 
    /// Contains methods to work with services 
    /// </summary> 
    public class YellowPages
    {
        public static List<AID> BackupListOfCompanyAgents
        {
            get;
            private set;
        }
        /// <summary> 
        /// Returns the AID of a service provider 
        /// </summary> 
        public static List<AID> FindService(string serviceName, string agentName, Agent myAgent, int timeOut)
        {
            List<AID> agents = new List<AID>();
            bool found = false;

            DateTime t1 = DateTime.Now;
            while (!found)
            {
                if ((DateTime.Now - t1).Seconds > timeOut)
                    break;
                Application.DoEvents();

                // search for an agent 

                //thiis implementation is not working
                //DFAgentDescription dfd = new DFAgentDescription();
                //ServiceDescription sd = new ServiceDescription();
                //sd.setType(serviceName);
                //dfd.addServices(sd);
                //try
                //{
                //    DFAgentDescription[] result = DFService.search(myAgent, dfd);
                //    if (result != null && result.Length > 0)
                //    {
                //        if (agentName == string.Empty) // any solver 
                //        {
                //            for (int i = 0; i < result.Length; i++)
                //                agent.Add(result[i].getName()); // one agent is enough 6 the first 
                //            found = true;
                //        }
                //        else
                //        {
                //            for (int i = 0; i < result.Length; i++)
                //            {
                //                // it is possible to look for a long name, not only local name 
                //                if (result[i].getName().getLocalName() == agentName)
                //                {
                //                    agent.Add(result[i].getName());
                //                    found = true;
                //                    break;
                //                }
                //            }
                //        }
                //    }
                //}
                //catch (Exception fe)
                //{
                //    Console.WriteLine(fe.StackTrace);
                //}
                //return null;
                
                DFAgentDescription template = new DFAgentDescription();
                ServiceDescription sd = new ServiceDescription();
                sd.setType(serviceName);
                template.addServices(sd);
                try
                {
                    DFAgentDescription[] result = DFService.search(myAgent, template);
                    if (result != null && result.Length > 0)
                    {
                        if (agentName == string.Empty) // any solver 
                        {
                            for (int i = 0; i < result.Length; i++)
                                agents.Add(result[i].getName()); // one agent is enough 6 the first 
                            found = true;
                        }
                        else
                        {
                            for (int i = 0; i < result.Length; i++)
                            {
                                // it is possible to look for a long name, not only local name 
                                if (result[i].getName().getLocalName() == agentName)
                                {
                                    agents.Add(result[i].getName());
                                    found = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                catch (FIPAException fe)
                {
                    if (BackupListOfCompanyAgents == null)
                        BackupListOfCompanyAgents = new List<AID>();
                    if (BackupListOfCompanyAgents.Count == CompanyManager.Companies.Count)
                        return BackupListOfCompanyAgents;
                    //DFS search crashed for no reason apparently -> so send the stored AIDs
                }
            }

            return agents;
        }

        /// <summary>
        /// [NOT WORKING[
        /// </summary>
        /// <param name="agent"></param>
        /// <param name="svc"></param>
        /// <returns></returns>
        public AID[] searchDF(Agent agent, String svc)//String service
        {
            DFAgentDescription dfd = new DFAgentDescription();
            ServiceDescription sd = new ServiceDescription();
            dfd.setName(agent.getAID());
            sd.setType(svc);
            dfd.addServices(sd);

            SearchConstraints ALL = new SearchConstraints();
            ALL.setMaxResults(new java.lang.Long(-1));

            try
            {
                DFAgentDescription[] result = DFService.search(agent, dfd, ALL);
                AID[] agents = new AID[result.Length];
                for (int i = 0; i < result.Length; i++)
                    agents[i] = result[i].getName();
                return agents;

            }
            catch (FIPAException fe)
            {
                fe.printStackTrace();
            }

            return null;
        }

        /// <summary> 
        /// Registers a service on behalf of an agent 
        /// </summary> 
        public static void RegisterService(string serviceName, Agent myAgent)
        {
            if (BackupListOfCompanyAgents == null)
                BackupListOfCompanyAgents = new List<AID>();
            BackupListOfCompanyAgents.Add(myAgent.getAID());
            // Register the service in the yellow pages  
            DFAgentDescription dfd = new DFAgentDescription();
            dfd.setName(myAgent.getAID());
            ServiceDescription sd = new ServiceDescription();
            sd.setType(serviceName);
            sd.setName(serviceName);
            dfd.addServices(sd);
            DFService.register(myAgent, dfd);
           
            //THE search crashes for no reason
            //DFAgentDescription[] list = DFService.search(myAgent, dfd);
            //if (list.Length < 0)
            //{
            //    DFService.register(myAgent, dfd);
            //}
            //else
            //{
            //    DFService.modify(myAgent, dfd);
            //}
        }

        /// <summary> 
        /// Deregisters a service on behalf of an agent 
        /// </summary> 
        public static void DeregisterService(Agent myAgent)
        {
            DFService.deregister(myAgent);
        }

        /// <summary> 
        /// Handles the messages associated with the take down of an agent, and deregisters the service on its behalf 
        /// </summary> 
        public static void DeregisterServiceOnTakeDown(Agent myAgent)
        {
            DFService.deregister(myAgent);
            Console.WriteLine(
                "Agent " + myAgent.getLocalName() +
                " was taken down.\r\nAn unhandled exception probably occured.");
        }
    }
}
